package com.yuqih.common.websocket.monitor.impl;

import java.lang.reflect.InvocationTargetException;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.beanutils.PropertyUtils;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.DefaultConversionService;

import com.yuqih.common.dto.FieldSpecifiedUtils;
import com.yuqih.common.exception.CodedException;
import com.yuqih.common.websocket.monitor.IMonitorHandler;
import com.yuqih.common.websocket.monitor.MonitorAction;

public abstract class AbstractMonitorHandler implements IMonitorHandler {
	
	protected abstract Map<String, ParamDefinition> getParamDefinitions();
	
	@Override
	public int getInterval() {
		return 3 * 1000;
	}
	
	protected Object buildCondition(Map<String, Object> params) {
		
		if (params == null) {
			return null;
		}
		
		if (getConditionType() == null) {
			return null;
		}
		
		Object condition = FieldSpecifiedUtils.createProxyInstance(getConditionType());
		for (Entry<String, Object> entry : params.entrySet()) {
			try {
				PropertyUtils.setProperty(condition, entry.getKey(), entry.getValue());
			} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
				throw CodedException.from(e);
			}
		}
		return condition;
	}
	
	protected abstract Class<?> getConditionType();
	
	protected static final ConversionService conversionService = new DefaultConversionService();

	@Override
	public void preHandle(MonitorAction action) {
		
		buildParams(action);
		buildCondition(action);
		
	}
	
	protected void buildParams(MonitorAction action) {
		Map<String, Object> params = action.getParams();
		if (params == null) {
			return;
		}
		
		Map<String, ParamDefinition> paramDefinitions = getParamDefinitions();
		if (paramDefinitions == null) {
			action.setParams(null);
			return;
		}
		
		Iterator<Entry<String, Object>> iterator = params.entrySet().iterator();
		while (iterator.hasNext()) {
			Entry<String, Object> entry = iterator.next();
			ParamDefinition definition = paramDefinitions.get(entry.getKey());
			if (definition == null) {
				iterator.remove();
				continue;
			}
			
			if (entry.getValue() != null) {
				entry.setValue(conversionService.convert(entry.getValue(), definition.getParamType()));
			}
			
			if (entry.getValue() == null && !definition.isNullable()) {
				iterator.remove();
				continue;
			}
			
		}
		
		if (params.isEmpty()) {
			action.setParams(null);
			return;
		}
	}
	
	protected void buildCondition(MonitorAction action) {
		if (action.getParams() == null) {
			return;
		}
		Object condition = buildCondition(action.getParams());
		action.setCondition(condition);
	}
}
